package cn.edu.pzhu.javaweb.util;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Random;

/**
 * 图像生成工具类
 * 用于生成包含随机字符的图像，常用于验证码等功能
 */
public class ImageGenerator {
    
    // 私有成员：图像和图像上的文本
    private BufferedImage image;
    private String text;
    
    // 随机数生成器
    private static final Random random = new Random();
    
    // 定义可用的字符集（数字+字母）
    private static final String CHARACTERS = 
        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    
    /**
     * 生成图像的初始化方法
     * @param width 图像宽度
     * @param height 图像高度
     * @param charCount 绘制字符的数量
     */
    public void initialize(int width, int height, int charCount) {
        // 1. 创建BufferedImage对象
        this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        
        // 2. 获取Graphics2D对象用于绘制
        Graphics2D g2d = this.image.createGraphics();
        
        // 3. 设置背景色（白色）
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, width, height);
        
        // 4. 设置字体
        Font font = new Font("Arial", Font.BOLD, height * 2 / 3);
        g2d.setFont(font);
        
        // 5. 生成随机字符并绘制
        this.text = generateRandomText(charCount);
        drawText(g2d, width, height, this.text);
        
        // 6. 添加干扰线（可选，增强安全性）
        addNoise(g2d, width, height);
        
        // 7. 释放图形资源
        g2d.dispose();
    }
    
    /**
     * 生成指定长度的随机字符串
     * @param charCount 字符数量
     * @return 随机字符串
     */
    private String generateRandomText(int charCount) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < charCount; i++) {
            int index = random.nextInt(CHARACTERS.length());
            sb.append(CHARACTERS.charAt(index));
        }
        return sb.toString();
    }
    
    /**
     * 在图像上绘制文本
     * @param g2d Graphics2D对象
     * @param width 图像宽度
     * @param height 图像高度
     * @param text 要绘制的文本
     */
    private void drawText(Graphics2D g2d, int width, int height, String text) {
        // 计算字符间距和起始位置
        int charWidth = width / (text.length() + 1);
        int startX = charWidth / 2;
        int baseY = height * 3 / 4; // 文本基线位置
        
        // 逐个绘制字符
        for (int i = 0; i < text.length(); i++) {
            // 设置随机颜色（黑色到深灰色）
            int grayValue = random.nextInt(50); // 0-49的灰度值
            g2d.setColor(new Color(grayValue, grayValue, grayValue));
            
            // 添加轻微的随机位置偏移
            int x = startX + i * charWidth + random.nextInt(5) - 2;
            int y = baseY + random.nextInt(5) - 2;
            
            // 添加轻微的旋转
            double angle = Math.toRadians(random.nextInt(15) - 7); // -7°到+7°
            g2d.rotate(angle, x, y);
            
            // 绘制字符
            g2d.drawString(String.valueOf(text.charAt(i)), x, y);
            
            // 恢复旋转
            g2d.rotate(-angle, x, y);
        }
    }
    
    /**
     * 添加干扰线（增强图像安全性）
     * @param g2d Graphics2D对象
     * @param width 图像宽度
     * @param height 图像高度
     */
    private void addNoise(Graphics2D g2d, int width, int height) {
        // 设置干扰线颜色（浅灰色）
        g2d.setColor(new Color(0, 0, 0));
        
        // 添加多条干扰线
        for (int i = 0; i < 50; i++) {
            int x1 = random.nextInt(width);
            int y1 = random.nextInt(height);
            int x2 = random.nextInt(width);
            int y2 = random.nextInt(height);
            g2d.drawLine(x1, y1, x2, y2);
        }
        
        // 添加干扰点
        for (int i = 0; i < 50; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            g2d.fillRect(x, y, 1, 1);
        }
    }
    
    // 提供对外部的get方法
    
    /**
     * 获取生成的图像
     * @return BufferedImage对象
     */
    public BufferedImage getImage() {
        return this.image;
    }
    
    /**
     * 获取图像上的文本
     * @return 文本字符串
     */
    public String getText() {
        return this.text;
    }
    
    /**
     * 将图像转换为字节数组（便于网络传输或存储）
     * @param format 图像格式，如 "PNG", "JPEG"
     * @return 图像字节数组
     * @throws IOException 如果转换失败
     */
    public byte[] getImageBytes(String format) throws IOException {
        if (this.image == null) {
            throw new IllegalStateException("图像未初始化，请先调用initialize方法");
        }
        
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(this.image, format, baos);
        return baos.toByteArray();
    }
    
    /**
     * 便捷方法：直接生成图像并返回
     * @param width 图像宽度
     * @param height 图像高度
     * @param charCount 字符数量
     * @return 包含图像和文本的ImageGenerator实例
     */
    public static ImageGenerator create(int width, int height, int charCount) {
        ImageGenerator generator = new ImageGenerator();
        generator.initialize(width, height, charCount);
        return generator;
    }
    
    /**
     * 测试方法
     */
    public static void main(String[] args) {
        try {
            // 创建图像生成器实例
            ImageGenerator generator = new ImageGenerator();
            
            // 初始化图像：宽200px，高80px，4个字符
            generator.initialize(200, 80, 4);
            
            // 获取生成的文本
            String generatedText = generator.getText();
            System.out.println("生成的文本: " + generatedText);
            
            // 获取图像字节数组（PNG格式）
            byte[] imageBytes = generator.getImageBytes("PNG");
            System.out.println("图像大小: " + imageBytes.length + " 字节");
            
            // 使用便捷方法创建
            ImageGenerator generator2 = ImageGenerator.create(150, 60, 6);
            System.out.println("便捷方法生成的文本: " + generator2.getText());
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}